/* 
   xmunipack - coordinates
   
   Copyright © 1997-2011 F.Hroch (hroch@physics.muni.cz)
   
   This file is part of Munipack.
   
   Munipack is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
   
   Munipack is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   
   You should have received a copy of the GNU General Public License
   along with Munipack.  If not, see <http://www.gnu.org/licenses/>.

*/

#include "fits.h"
#include <wx/wx.h>

#ifdef __WXDEBUG__
#include <wx/debug.h>
#endif

FitsCoo::FitsCoo(): FitsArray(), type(COO_PIXEL), haswcs(false)
{
  crpix1 = crpix2 = crval1 = crval2 = cd1_1 = cd1_2 = cd2_1 = cd2_2 = 0.0;
}

FitsCoo::FitsCoo(const FitsArray& a): FitsArray(a),type(COO_PIXEL),haswcs(false)
{
  // decode WCS

  if( a.GetKey("CTYPE1").Find("TAN") != wxNOT_FOUND &&
      a.GetKey("CTYPE2").Find("TAN") != wxNOT_FOUND ) {
    haswcs = true;
    crpix1 = a.GetKeyDouble("CRPIX1");
    crpix2 = a.GetKeyDouble("CRPIX2");
    crval1 = a.GetKeyDouble("CRVAL1");
    crval2 = a.GetKeyDouble("CRVAL2");
    cd1_1 = a.GetKeyDouble("CD1_1");
    cd1_2 = a.GetKeyDouble("CD1_2");
    cd2_1 = a.GetKeyDouble("CD2_1");
    cd2_2 = a.GetKeyDouble("CD2_2");
  }
  else
    crpix1 = crpix2 = crval1 = crval2 = cd1_1 = cd1_2 = cd2_1 = cd2_2 = 0.0;

}
  
void FitsCoo::SetType(coords_type t)
{
  type = t;
}

coords_type FitsCoo::GetType() const
{
  return type;
}

void FitsCoo::GetEq(int xcen, int ycen, double& alpha, double& delta)
{ 
  double x,y,u,v;

  u = xcen - crpix1;
  v = ycen - crpix2;

  x = u*cd1_1 + v*cd1_2;
  y = u*cd2_1 + v*cd2_2;


  // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  // TEMPORARY A SIMPLE GNOMONICAL APPROXIMATION ONLY!!!!!!
  // !!!    UNACCURATE !!!!!!!
  delta = y + crval2;
  alpha = x*cos(delta/57.295779513082322865) + crval1;
  //  wxLogDebug("%f %f %f %f %f %f",u,v,x,y,alpha,delta);
}


void FitsCoo::RaSix(double alpha, int& h, int& min, double& sec)
{
  double x = alpha/15.0;
  h = int(x);
  min = int(60.0*(x - h));
  sec = 3600.0*(x - (h + min/60.0));
}

void FitsCoo::DecSix(double delta, char& sign, int& d, int& m, double& s)
{
  sign = delta > 0.0 ? '+' : '-';

  double y = fabs(delta);
  d = int(y);
  m = int(60.0*(y - d));
  s = 3600.0*(y - (d + m/60.0));
}


wxString FitsCoo::Get_str(int i, int j)
{ 
  wxString a,b;
  GetStr(i,j,a,b);

  if( a.IsEmpty() || a.IsEmpty() )
    return wxEmptyString;

  if( type == COO_PIXEL )
    return "x=" + a + "  y=" + b;
  else
    return "α=" + a + "  δ=" + b;
}


void FitsCoo::GetStr(int i, int j, wxString& a, wxString& b)
{ 
  int h,min,d,m;
  double x,y, sec,s;
  char sg;

  a.Clear();
  b.Clear();

  if( 0 <= i && i < Width() && 0 <= j && j < Height() ) {

    if( type == COO_PIXEL ) {
      a.Printf("%d",i+1);
      b.Printf("%d",j+1);
    }
    else if( haswcs ) {

      GetEq(i,j,x,y); 

      if( type == COO_EQDEG ) {
	a.Printf("%.5f°(?)",x);
	b.Printf("%.5f°(?)",y);
      }

      else if( type == COO_EQSIX ) {
	RaSix(x,h,min,sec); 
	DecSix(y,sg,d,m,s);
	a.Printf("%02d:%02d:%06.3fs(?)",h,min,sec);
	b.Printf("%c%02d°%02d'%05.2f\"(?)",sg,d,m,s);
      }
    }
  }
}



wxString FitsCoo::Label_str(int n)
{
  switch(n){
  case COO_PIXEL: return "pixels";
  case COO_EQDEG: return "Equatorial (°)";
  case COO_EQSIX: return "Equatorial (h:m:s)";
  default:        return wxEmptyString;
  }
}

wxArrayString FitsCoo::Label_str()
{
  wxArrayString a;

  for(int i = COO_FIRST+1; i < COO_LAST; i++)
    a.Add(Label_str(i));

  return a;
}
